package org.kardigen.lg.service.server;

import java.lang.reflect.Method;

import javax.jdo.FetchPlan;
import javax.jdo.PersistenceManager;
import javax.jdo.identity.StringIdentity;

import com.google.gwt.requestfactory.shared.Locator;

public class LgGenericLocator extends Locator<Object, Object> {

	@Override
	public Object create(Class<? extends Object> clazz) {
		try {
			return clazz.newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public Object find(Class<? extends Object> clazz, Object id) {
		
		if (id == null) {
			return null;
		}
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			// String[] strings = ((String) id).split(":");
//			Class<?> keyclazz = Class.forName(strings[0]);
			pm.getFetchPlan().addGroup(FetchPlan.ALL);

			StringIdentity stringIdentity = new StringIdentity(clazz, (String) id);
			Object object = pm.getObjectById(stringIdentity);
			return clazz.cast(object);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			pm.close();
		}
	}

	@Override
	public Class<Object> getDomainType() {
		// hack probably it is not uset
		throw new UnsupportedOperationException();
	}

	@Override
	public Object getId(Object domainObject) {
		if (domainObject == null) {
			return null;
		}

		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Method method = domainObject.getClass().getMethod("getId");
			return method.invoke(domainObject);
			// StringIdentity identity = (StringIdentity)
			// pm.getObjectId(domainObject);
			// if (identity == null) {
			// return null;
			// }
			//
			// return identity.getTargetClassName() + ":" + identity.getKey();

		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			pm.close();
		}
	}

	@Override
	public Class<Object> getIdType() {
		return (Class) String.class;
	}

	@Override
	public Object getVersion(Object domainObject) {
		try {
			return domainObject.getClass().getMethod("getVersion").invoke(domainObject);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	
}
